package com.example.newfolder.Controller;

import com.FileBehavior.FileHelp;
import com.FileBehavior.FileIO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.http.BaiduOAuthConfig;
import com.http.BaiduPanConfig;
import com.http.HttpRequest;
import com.util.Folders;
import com.util.SQLHelp;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Controller
public class BaiduController {



    @RequestMapping("/baidu_oauth_index")
    public String baiduOAuthIndex(@RequestParam("index") Integer index, HttpServletResponse response){
        response.addCookie(new Cookie("baiduOauthIndex", index.toString()));
        return "baidu_oauth_index";
    }

    @GetMapping("/baidu_oauth")
    public String baiduOAuth(HttpSession session){
        // https://blog.csdn.net/qq_40065776/article/details/105418674
        String url = BaiduOAuthConfig.getOAuthCodeUrl();
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        session.setAttribute("state", uuid);
        url = "redirect:https://" + url + "&state=" + uuid;
        return url;
    }

    @GetMapping("/callback")
    public String baiduCallback(HttpServletRequest request){
        String code = request.getParameter("code");
        return code;
    }

    @ResponseBody
    @RequestMapping("/submit_code")
    public JSONObject submitCode(@RequestParam("code") String code, @CookieValue(value = "userId", defaultValue = "0") String userId, @CookieValue(value = "baiduOauthIndex", defaultValue = "0")String baiduOauthIndex){
        JSONObject jsonObject = new JSONObject();
        if(userId.equals("0")){
            jsonObject.put("res", "user_error");
            return jsonObject;
        }
        Integer u = Integer.parseInt(userId);
        Integer b = Integer.parseInt(baiduOauthIndex);
        String accessToken = BaiduOAuthConfig.getUserTokenFromBaiDu(u, b, code);
        if(accessToken == null){
            jsonObject.put("res", "net_error");
            return jsonObject;
        }else if(accessToken == "token_error"){
            jsonObject.put("res", accessToken);
        }else if(accessToken == "info_error"){
            jsonObject.put("res", accessToken);
        }else if(accessToken == "pan_repeat"){
            jsonObject.put("res", accessToken);
        }else{
            jsonObject.put("res", "suc");
        }
        return jsonObject;
    }
    @RequestMapping("/get_folder_all_file")
    public String getFolderAllFile(@RequestParam(value = "folder_key") String folderKey,
                                   @CookieValue(value = "userId", defaultValue = "0") String userId,
                                   @ModelAttribute(value = "folderFileView")FolderFileView folderFileView) throws IOException {
        JSONObject result = new JSONObject();
        String sqlFormat = "select * from folder where folder_key = '%s'";
        String sql = String.format(sqlFormat, folderKey);
        ArrayList<HashMap<String, String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            return "redirect:/index";
        }
        if(!res.get(0).get("user_id").equals(userId)){
            // 不是你的不能看
            return "redirect:/index";
        }
        String pan_id = res.get(0).get("pan_id");
        if(pan_id.equals("0")){
            return "redirect:/index";
        }
        String accessToken = BaiduOAuthConfig.checkAndGetPanAccessToken(Integer.parseInt(pan_id));
        if(accessToken.equals("")){
            return "redirect:/index";
        }
        String url = BaiduPanConfig.getFileListUrl(accessToken, folderKey);
        result = HttpRequest.PostRequest(url);
        if(result.get("errno").equals(-9)){
            folderFileView.setFileList(new ArrayList<FileView>());
            return "files";
        }
        if(result.get("errno").equals(-7)){
            folderFileView.setFileList(new ArrayList<FileView>());
            return "files";
        }
        JSONArray files = (JSONArray)result.get("list");
        ArrayList<FileView> list = new ArrayList<>();
        for (Object file:files){
            JSONObject o = (JSONObject) JSON.toJSON(file);
            String name = o.get("server_filename").toString();
            String size = o.get("size").toString();
            String fsids = o.get("fs_id").toString();
            HashMap<String,String> hash = new HashMap<>();
            hash.put("server_filename",name);
            hash.put("size",size);
            hash.put("fsids",fsids);
            list.add(new FileView(hash));
        }
        folderFileView.setFolderKey(folderKey);
        folderFileView.setFileList(list);

        return "files";
    }

    @RequestMapping("/upload_file")
    public String uploadFile(HttpServletRequest request, @ModelAttribute("nameList") ArrayList<String> nameList,
                             @ModelAttribute("folderView")FolderView folderView){
        String folderKey = request.getParameter("folder_key");
        String sqlFormat = "select * from folder where folder_key = '%s'";
        String sql = String.format(sqlFormat, folderKey);
        ArrayList<HashMap<String, String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            return "redirect:/index";
        }
        HashMap<String, String> h = res.get(0);
        nameList.add(h.get("first_name"));
        nameList.add(h.get("second_name"));
        folderView.setFolderView(h);
        return "upload_file";
    }

    @RequestMapping("/test_upload_file")
    public String testUploadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        InputStream is = request.getInputStream();

        // 头中获取文件名
        String filename = request.getHeader("filename");
        // 先创建文件
        File file = new File("D:\\1\\" + filename);
        if(file.exists()){
            // 覆盖原来的
            file.delete();
        }
        // 写文件
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int len = 0;
        while(-1!=(len = is.read(buf))){
            fos.write(buf, 0, len);
        }
        fos.flush();
        fos.close();
        return "redirect:login";
    }
    @ResponseBody
    @RequestMapping("/upload_file_url")
    public JSONObject uploadFileUrl(HttpServletRequest request, @RequestParam(value = "file")MultipartFile file) throws IOException {
        String folderKey = request.getParameter("folder_key");
        String name = request.getParameter("name");
        String fileNameParam = request.getParameter("fileNameParam");
        JSONObject fileNameParamObject = JSONObject.parseObject(fileNameParam);
        JSONObject result = new JSONObject();
        String sqlFormat = "select * from folder where folder_key = '%s'";
        String sql = String.format(sqlFormat, folderKey);
        ArrayList<HashMap<String, String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            result.put("res", "folder_error");
            return result;
        }
        String _chunks = request.getParameter("chunks");
        String _chunk = request.getParameter("chunk");
        Integer chunks = Integer.parseInt(_chunks);
        Integer chunk = Integer.parseInt(_chunk);
        String filePath = FileIO.saveFile(file, Folders.getFolderFileName(folderKey, (String) fileNameParamObject.get(0), (String) fileNameParamObject.get(1), name), chunk == 0);
        if(filePath == null){
            result.put("res", "upload_error");
            return result;
        }
        if(chunks > chunk + 1){
            // 还没到最后一个
            result.put("res", "uploading");
            return result;
        }
        if(Folders.saveFolderFile(filePath, folderKey)){
            result.put("res", "suc");
        }else{
            result.put("res", "upload_error");
        }

        return result;
    }

    @ResponseBody
    @RequestMapping("/delete_files")
    public JSONObject deleteFiles(HttpServletRequest request, @CookieValue("userId") String userId) throws IOException {
        String fileName = request.getParameter("fileName");
        JSONObject result = new JSONObject();
        JSONArray fileArray = JSONArray.parseArray(fileName);
        if(fileArray.size() == 0){
            result.put("res", "suc");
            return result;
        }
        String[] fileNames = new String[fileArray.size()];
        fileArray.toArray(fileNames);
        String folderKey = request.getParameter("folder_key");

        String sqlFormat = "select * from folder where folder_key = '%s'";
        String sql = String.format(sqlFormat, folderKey);
        ArrayList<HashMap<String, String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            result.put("res", "folder_error");
            return result;
        }
        if(!res.get(0).get("user_id").equals(userId)){
            // 不是你的不能删除
            result.put("res", "user_error");
            return result;
        }
        String pan_id = res.get(0).get("pan_id");
        if(pan_id.equals("0")){
            result.put("res", "pan_error");
            return result;
        }
        String accessToken = BaiduOAuthConfig.checkAndGetPanAccessToken(Integer.parseInt(pan_id));
        if(accessToken.equals("")){
            result.put("res", "token");
            return result;
        }
        if(!BaiduPanConfig.deleteFile(accessToken, folderKey, fileNames)){
            result.put("res", "net_error");
            return result;
        }
        result.put("res", "suc");
        return result;
    }

    @RequestMapping("previewFile")
    public String previewFile(HttpServletRequest request, @CookieValue("userId")String userId, @ModelAttribute("downloadView")DownloadView downloadView) throws IOException {
        String fsids = request.getParameter("fsids");
        String folderKey = request.getParameter("folder_key");
        String fileName = request.getParameter("file_name");
        String sqlFormat = "select * from folder where folder_key = '%s'";
        String sql = String.format(sqlFormat, folderKey);
        ArrayList<HashMap<String, String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            return "redirect:/index";
        }
        if(!res.get(0).get("user_id").equals(userId)){
            return "redirect:/index";
        }
        String pan_id = res.get(0).get("pan_id");
        if(pan_id.equals("0")){
            return "redirect:/index";
        }
        String accessToken = BaiduOAuthConfig.checkAndGetPanAccessToken(Integer.parseInt(pan_id));
        if(accessToken.equals("")){
            return "redirect:/index";
        }
        downloadView.src = BaiduPanConfig.previewFile(accessToken, fsids, fileName);
        return "redirect:/download_file?src=" + URLEncoder.encode(downloadView.src, "UTF-8");
    }

    @ResponseBody
    @RequestMapping("download_file")
    public void downloadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String src = request.getParameter("src");
        src = URLDecoder.decode(src, "UTF-8");
        String abso = FileHelp.relaPathToAbsoPath(src);
        File file = new File(abso);
        if(!file.exists()){
            System.out.println("文件不存在不可下载" + abso);
            return;
        }
        System.out.println("文件下载...");
        // 回复头
        // 跟上面的头不一样
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));

        FileInputStream fis = new FileInputStream(file);
        OutputStream os = response.getOutputStream();
        int len;
        byte[] buf = new byte[1024];
        while(-1!=(len=fis.read(buf))){
            os.write(buf, 0, len);
        }
        fis.close();
        os.flush();
        os.close();

    }

    @ResponseBody
    @RequestMapping("/hello")
    public Map<String, Object> say(){
        Map<String, Object> map = new HashMap<>();
        map.put("code", "200");
        map.put("data", "suc");
        return map;
    }

}

class FolderFileView{
    public ArrayList<FileView> fileList;

    public String folderKey;
    public FolderFileView(){}

    public void setFileList(ArrayList<FileView> _fileList){
        fileList = _fileList;
    }

    public void setFolderKey(String folderKey) {
        this.folderKey = folderKey;
    }
}

class FileView{
    public String fileName;
    public String size;
    public String fsids;

    public FileView(HashMap<String,String> file){
        this.fileName = file.get("server_filename");
        this.size = file.get("size");
        this.fsids = file.get("fsids");
    }
}

class DownloadView{
    public String src;
}